﻿#define _CRT_SECURE_NO_WARNINGS 1


//#include<iostream>
//
//using namespace std;
//
//// 由于引⽤折叠限定，Func1实例化以后总是⼀个左值引⽤
//template<class T>
//void Func1(T& x)
//{
//
//}
//
//// 由于引⽤折叠限定，Func2实例化以后可以是左值引⽤，也可以是右值引⽤
//template<class T>
//void Func2(T&& x)
//{
//
//}
//
//int main()
//{
//	typedef int& lref;
//	typedef int&& rref;
//	int n = 0;
//
//	lref& r1 = n; // r1 的类型是 int&
//	lref&& r2 = n; // r2 的类型是 int&
//	rref& r3 = n; // r3 的类型是 int&
//	rref&& r4 = 1; // r4 的类型是 int&&
//
//	// 没有折叠->实例化为void f1(int& x)
//	Func1<int>(n);
//	//Func1<int>(0); // 报错
//	
//	// 折叠->实例化为void f1(int& x)
//	Func1<int&>(n);
//	//Func1<int&>(0); // 报错
//	
//	// 折叠->实例化为void f1(int& x)
//	Func1<int&&>(n);
//	//Func1<int&&>(0); // 报错
//	
//	// 折叠->实例化为void f1(const int& x)
//	Func1<const int&>(n);
//	Func1<const int&>(0);
//
//	// 折叠->实例化为void f1(const int& x)
//	Func1<const int&&>(n);
//	Func1<const int&&>(0);
//
//	// 没有折叠->实例化为void f2(int&& x)
//	//Func2<int>(n); // 报错
//	Func2<int>(0);
//
//	// 折叠->实例化为void f2(int& x)
//	Func2<int&>(n);
//	//Func2<int&>(0); // 报错
//
//	// 折叠->实例化为void f2(int&& x)
//	//Func2<int&&>(n); // 报错
//	Func2<int&&>(0);
//
//
//	return 0;
//}


//#include<iostream>
//
//using namespace std;
//
//template<class ...Args>
//void Print(Args... args)
//{
//	cout << sizeof...(args) << endl;
//}
//
//int main()
//{
//	double x = 2.2;
//	Print(); // 包⾥有0个参数
//	Print(1); // 包⾥有1个参数
//	Print(1, string("xxxxx")); // 包⾥有2个参数
//	Print(1.1, string("xxxxx"), x); // 包⾥有3个参数
//
//	return 0;
//}


//#include<string>
//#include<iostream>
//
//using namespace std;
//
//template<class T>
//const T& GetArgs(const T& x)
//{
//	cout << x << ' ';
//	return x;
//}
//
//template<class ...Args>
//void Arguments(Args... args)
//{
//
//}
//
//template<class ...Args>
//void Print(Args... args)
//{
//	Arguments(GetArgs(args)...);
//}
//
//int main()
//{
//	Print(10, 3.14, string("hello"));// 底层是递归处理，所以从最后一个参数开始打印
//
//	return 0;
//}


//#include<iostream>
//
//using namespace std;
//
//class SqTable
//{
//public:
//	SqTable(const char* str = " ")
//		:_size(strlen(str))
//		, _capacity(_size)
//	{
//		cout << "构造" << endl;
//
//		_str = new char[_capacity + 1];
//		strcpy(_str, str);
//	}
//
//	SqTable(const SqTable& st)
//		:_str(nullptr)
//	{
//		cout << "拷贝构造" << endl;
//
//		_str = new char[st._capacity + 1];
//		strcpy(_str, st._str);
//		_size = st._size;
//		_capacity = st._capacity;
//	}
//
//	void swap(SqTable& st)
//	{
//		std::swap(_str, st._str);
//		std::swap(_size, st._size);
//		std::swap(_capacity, st._capacity);
//	}
//
//	SqTable(SqTable&& st)
//	{
//		cout << "移动构造" << endl;
//
//		swap(st);
//	}
//
//	SqTable& operator=(const SqTable& st)
//	{
//		cout << "拷贝赋值" << endl;
//
//		if (this != &st)
//		{
//			_str[0] = '\0';
//			_str = new char[st._capacity + 1];
//			strcpy(_str, st._str);
//			_size = st._size;
//			_capacity = st._capacity;
//		}
//
//		return *this;
//	}
//
//	SqTable& operator=(SqTable&& st)
//	{
//		cout << "移动赋值" << endl;
//		swap(st);
//		return *this;
//	}
//
//private:
//	char* _str;
//	size_t _size;
//	size_t _capacity;
//};
//
//class Person
//{
//public:
//	Person(const char* tables = " ")
//		:_tables(tables)
//	{ }
//
//	Person(const Person& p)
//		:_tables(p._tables)
//	{ }
//
//	Person(Person&& p) = default;
//
//	//Person(const Person& p) = delete;
//	
//private:
//	SqTable _tables;
//};
//
//int main()
//{
//	Person s1;
//	Person s2 = s1;
//	Person s3 = move(s1);
//	Person s4;
//
//	return 0;
//}


//#include<iostream>
//
//using namespace std;
//
//int main()
//{
//	auto Add1 = [](int x, int y)->int {return x + y; };
//	cout << Add1(10, 20) << endl;
//
//	// 1、捕捉为空也不能省略
//	// 2、参数为空可以省略
//	// 3、返回值可以省略，可以通过返回对象⾃动推导
//	// 4、函数题不能省略
//	auto Func1 = []
//	{
//		cout << "hello world" << endl;
//		return 0;
//	};
//
//	Func1();
//
//	return 0;
//}


//#include<iostream>
//
//using namespace std;
//
//int x = 0;
//// 捕捉列表必须为空，因为全局变量不⽤捕捉就可以⽤，没有可被捕捉的变量
//auto Func1 = []()
//{
//	x++;
//};
//
//int main()
//{
//	// 只能⽤当前lambda局部域和捕捉的对象和全局对象
//	int a = 0, b = 1, c = 2, d = 3;
//	auto Func1 = [a, &b]
//	{
//		// 值捕捉的变量不能修改，引⽤捕捉的变量可以修改
//		//a++;
//		b++;
//		int ret = a + b;
//
//		return ret;
//	};
//	cout << Func1() << endl;
//
//	// 隐式值捕捉
//	// ⽤了哪些变量就捕捉哪些变量
//	auto Func2 = [=]
//	{
//		int ret = a + b + c;
//
//		return ret;
//	};
//	cout << Func2() << endl;
//
//	// 隐式引⽤捕捉
//	// ⽤了哪些变量就捕捉哪些变量
//	auto Func3 = [&]
//	{
//		a++;
//		c++;
//		d++;
//	};
//	Func3();
//	cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
//
//	// 混合捕捉1
//	auto Func4 = [&, a, b]
//	{
//		//a++;
//		//b++;
//		c++;
//		d++;
//
//		return a + b + c + d;
//	};
//	Func4();
//	cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
//
//	// 混合捕捉2
//	auto Func5 = [=, &a, &b]
//	{
//		a++;
//		b++;
//		/*c++;
//		d++;*/
//
//		return a + b + c + d;
//	};
//	Func5();
//	cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
//
//	// 局部的静态和全局变量不能捕捉，也不需要捕捉
//	static int m = 0;
//	auto Func6 = []
//	{
//		int ret = x + m;
//
//		return ret;
//	};
//
//	// 传值捕捉本质是⼀种拷⻉,并且被const修饰了
//	// mutable相当于去掉const属性，可以修改了
//	// 但是修改了不会影响外⾯被捕捉的值，因为是⼀种拷⻉
//	auto Func7 = [=]()mutable
//	{
//		a++;
//		b++;
//		c++;
//		d++;
//
//		return a + b + c + d;
//	};
//	cout << Func7() << endl;
//	cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
//
//	return 0;
//}


#include<functional>
#include<iostream>

using namespace std;

template<class T>
void DeleteArrarFunc(T* ptr)
{
	delete[] ptr;
}

namespace yyh
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			,_pcount(new int(1))
		{ }

		template<class D>
		shared_ptr(T* ptr, D del)
			:_ptr(ptr)
			,_pcount(new int(1))
			,_del(del)
		{ }

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			,_pcount(sp._pcount)
			,_del(sp._del)
		{
			(*_pcount)++;
		}

		void release()
		{
			if (--(*_pcount) == 0)
			{
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				(*_pcount)++;
				_del = sp._del;
			}

			return *this;
		}

		~shared_ptr()
		{
			release();
		}

		T* get() const
		{
			return _ptr;
		}

		int use_count() const
		{
			return *_pcount;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return &_ptr;
		}

	private:
		T* _ptr;
		int* _pcount;
		function<void(T*)> _del = [](T* ptr) { delete ptr; };
	};
}

int main()
{
	yyh::shared_ptr<int> ptr1;

	yyh::shared_ptr<int> ptr2(new int[5], DeleteArrarFunc<int>);

	yyh::shared_ptr<int> ptr3(ptr2);

	yyh::shared_ptr<int> ptr4;
	ptr4 = ptr2;



	return 0;
}